#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <error.h>
#include <string.h>

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << "<port>" << std::endl;
        return -1;
    }

    int listenfd;
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        std::cerr << "Error creating socket: " << strerror(errno) << std::endl;
        return -1;
    }

    struct sockaddr_in servaddr;
    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(atoi(argv[1]));

    if (bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr))) { 
        std::cerr << "Error binding socket: " << strerror(errno) << std::endl;
        close(listenfd); 
        return -1; 
    }

    if (listen(listenfd, 5)) {
        std::cerr << "Error listening on socket: " << strerror(errno) << std::endl;
        close(listenfd);
        return -1;
    }

    int clientfd = accept(listenfd,0,0);
    if (clientfd < 0) {
        std::cerr << "Error accepting connection: " << strerror(errno) << std::endl;
        close(listenfd);
        return -1;
    }

    while(1) {
        int iret;
        char buffer[1024];

        if ((iret = recv(clientfd, buffer, sizeof(buffer), 0)) <= 0) {
            std::cerr << "receiving message: " << strerror(errno) << std::endl;
            if (iret == 0) {
                std::cout << "Client disconnected." << std::endl;
            }
            break;
        }
        buffer[iret] = '\0';
        std::cout << "recv: " << buffer << std::endl;

        if ((iret = send(clientfd, buffer, strlen(buffer), 0)) <= 0) {
            std::cerr << "Error sending message: " << strerror(errno) << std::endl;
            break;
        } else {
            std::cout << "send: " << buffer << std::endl;
        }
    }

    close(listenfd);
    close(clientfd);
    return 0;
}